package com.giggle.nacos.helper;

import com.alibaba.cloud.dubbo.registry.SpringCloudRegistryFactory;
import com.giggle.common.helper.ReflectHelper;
import com.giggle.common.helper.SpringBeanHelper;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.config.ApplicationConfig;
import org.apache.dubbo.config.ReferenceConfig;
import org.apache.dubbo.config.RegistryConfig;
import org.apache.dubbo.config.spring.extension.SpringExtensionFactory;
import org.apache.dubbo.rpc.service.GenericService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.env.Environment;
import org.springframework.util.Assert;

import java.util.*;

/**
 * @author guozichen
 * @ClassName:
 * @Description: (这里用一句话描述累的作用)
 * @date 2020/8/26 17:27
 */
public class NacosHelper {

    public static final Logger logger = LoggerFactory.getLogger(NacosHelper.class);
    public static final HashMap<String, String> configMap = new HashMap();
    public static final String URL_GROUP_KEY = "group";
    public static final String ENV_GROUP_KEY = "nacos.service.group";
    public static final String URL_NAMESPACE_KEY = "namespace";
    public static final String ENV_NAMESPACE_KEY = "nacos.service.namespace";
    public static final String PROTOCOL_NACOS_X = "nacosx";
    public static final String PROVIDER = "provider";
    public static final int SERVICE_TIME_OUT = 60000;
    public static final String GENERIC = "true";
    public static final String ENV_METADATA_REGISTER_KEY = "nacos.service.metadata-enabled";
    public static final String ENV_SERVERADDR_KEY = "nacos.service.address";
    public static final int NACOS_DEFAULT_PORT = 8848;
    public static final String NACOS_DEFAULT_LOGGER = "slf4j";
    public static final String NACOS_DEFAULT_PREFIX = "dubbo.application";

    public NacosHelper() {
    }

    public static String getEnv(String propertyName, String defaultValue) {
        String propertyValue = defaultValue;
        Environment environment = (Environment)getBean(Environment.class);
        if (environment != null && StringUtils.isNotBlank(propertyName)) {
            propertyValue = environment.getProperty(propertyName);
            if (StringUtils.isNotBlank(propertyValue)) {
                propertyValue = propertyValue.trim();
            }
        }

        return propertyValue;
    }

    public static Boolean getMetadataRegisterEnabled() {
        Boolean registerEnabled = true;
        Environment environment = (Environment)getBean(Environment.class);
        if (environment != null) {
            String value = environment.getProperty(ENV_METADATA_REGISTER_KEY);
            if (StringUtils.isNotBlank(value)) {
                registerEnabled = Boolean.valueOf(value);
            }
        }

        return registerEnabled;
    }

    public static String getProviderGroupName() {
        return getEnv(ENV_GROUP_KEY, "DEFAULT_GROUP");
    }

    public static String getProviderGroupName(URL url) {
        String groupName = null;
        Environment environment = (Environment)getBean(Environment.class);
        if (environment != null) {
            groupName = environment.getProperty(ENV_GROUP_KEY);
        }

        if (groupName == null || groupName.trim().length() == 0) {
            groupName = url.getParameter(URL_GROUP_KEY, "DEFAULT_GROUP");
        }

        return groupName;
    }

    public static String getConsumerGroupName(URL url) {
        String groupName = url.getParameter(URL_GROUP_KEY, "DEFAULT_GROUP");
        return groupName;
    }

    public static String getNacosGroupName(URL url) {
        String groupName = null;
        String side = url.getParameter("side");
        if (PROVIDER.equals(side)) {
            groupName = getProviderGroupName(url);
        } else {
            groupName = getConsumerGroupName(url);
        }

        return groupName;
    }

    public static void putByNacosProperties(URL url, Properties properties) {
        Environment environment = (Environment)getBean(Environment.class);

        String urlkey;
        String envVal;
        for(Iterator var3 = configMap.entrySet().iterator(); var3.hasNext(); properties.setProperty(urlkey, envVal)) {
            Map.Entry<String, String> entry = (Map.Entry)var3.next();
            urlkey = (String)entry.getKey();
            String envKey = (String)entry.getValue();
            envVal = null;
            if (environment != null) {
                envVal = environment.getProperty(envKey);
            }

            if (envVal == null || envVal.trim().length() == 0) {
                envVal = url.getParameter(urlkey, "DEFAULT_GROUP");
            }
        }

    }

    public static <T> T getBean(Class<T> type) {
        Object bean = null;

        try {
            Set<ApplicationContext> applicationContexts = SpringExtensionFactory.getContexts();
            if (CollectionUtils.isNotEmpty(applicationContexts)) {
                Iterator var3 = applicationContexts.iterator();

                while(var3.hasNext()) {
                    ApplicationContext applicationContext = (ApplicationContext)var3.next();
                    bean = applicationContext.getBean(type);
                    if (bean != null) {
                        break;
                    }
                }
            }

            if (bean == null) {
                ConfigurableApplicationContext applicationContext = (ConfigurableApplicationContext)ReflectHelper.getStaticField(SpringCloudRegistryFactory.class, "applicationContext");
                bean = applicationContext.getBean(type);
            }

            if (bean == null) {
                bean = SpringBeanHelper.getBean(type);
            }
        } catch (BeansException var5) {
            bean = null;
        }

        return (T) bean;
    }

    public static URL handleUrl(URL url) {
        try {
            String protocol = url.getProtocol();
            if (PROTOCOL_NACOS_X.equals(protocol)) {
                String host = url.getHost();
                String serverAddr = null;
                if (StringUtils.isBlank(host)) {
                    serverAddr = getEnv(ENV_SERVERADDR_KEY, "127.0.0.1:8848");
                    String[] addr = serverAddr.split(":");
                    if (addr.length == 2) {
                        url = url.setHost(addr[0]);
                        url = url.setPort(Integer.valueOf(addr[1]));
                    }
                }
            }
        } catch (Exception var5) {
            logger.error(ExceptionUtils.getStackTrace(var5));
        }

        return url;
    }

    private static ApplicationConfig buildApplicationConfig(Environment environment) {
        String applicationName = environment.getProperty("spring.application.name", "giggle-application");
        ApplicationConfig applicationConfig = new ApplicationConfig();
        applicationConfig.setName(applicationName);
        applicationConfig.setLogger(NACOS_DEFAULT_LOGGER);
        applicationConfig.setQosEnable(false);
        applicationConfig.setId(applicationName);
        applicationConfig.setPrefix(NACOS_DEFAULT_PREFIX);
        return applicationConfig;
    }

    private static RegistryConfig buildRegistryConfig(Environment environment) {
        String serverAddress = environment.getProperty(ENV_SERVERADDR_KEY);
        if (StringUtils.isBlank(serverAddress)) {
            Assert.notNull(serverAddress, "not found nacos server config:addresss!");
        }

        String portStr = serverAddress.substring(serverAddress.indexOf(":"));

        int port;
        try {
            port = Integer.valueOf(portStr);
        } catch (NumberFormatException var5) {
            logger.warn("{} is not number. use default port:{}", portStr, NACOS_DEFAULT_PORT);
            port = NACOS_DEFAULT_PORT;
        }

        RegistryConfig registryConfig = new RegistryConfig();
        registryConfig.setProtocol(PROTOCOL_NACOS_X);
        registryConfig.setPort(port);
        registryConfig.setAddress("nacosx://" + serverAddress);
        registryConfig.setId(PROTOCOL_NACOS_X);
        return registryConfig;
    }

    public static GenericService getGenericService(String apiInterfaceName, String apiGroup, String apiVersion) {
        try {
            Environment environment = (Environment)SpringBeanHelper.getBean(Environment.class);
            ApplicationConfig applicationConfig = buildApplicationConfig(environment);
            RegistryConfig registryConfig = buildRegistryConfig(environment);
            Class<?> apiInterface = Class.forName(apiInterfaceName);
            ReferenceConfig reference = new ReferenceConfig();
            reference.setRegistry(registryConfig);
            reference.setApplication(applicationConfig);
            reference.setInterface(apiInterface);
            reference.setGroup(apiGroup);
            reference.setProtocol("dubbo");
            reference.setVersion(apiVersion);
            reference.setGeneric(GENERIC);
            reference.setTimeout(SERVICE_TIME_OUT);
            return (GenericService)reference.get();
        } catch (ClassNotFoundException var8) {
            var8.printStackTrace();
            return null;
        }
    }

    public static <T> T getDubboService(String apiInterfaceName, String apiGroup, String apiVersion) {
        Object t = null;

        try {
            Environment environment = (Environment)SpringBeanHelper.getBean(Environment.class);
            ApplicationConfig applicationConfig = buildApplicationConfig(environment);
            RegistryConfig registryConfig = buildRegistryConfig(environment);
            Class<?> apiInterface = Class.forName(apiInterfaceName);
            ReferenceConfig<T> reference = new ReferenceConfig();
            reference.setRegistry(registryConfig);
            reference.setApplication(applicationConfig);
            reference.setInterface(apiInterface);
            reference.setGroup(apiGroup);
            reference.setProtocol("dubbo");
            reference.setVersion(apiVersion);
            reference.setTimeout(SERVICE_TIME_OUT);
            t = reference.get();
        } catch (ClassNotFoundException var9) {
            var9.printStackTrace();
        }

        return (T) t;
    }

    static {
        configMap.put(URL_GROUP_KEY, ENV_GROUP_KEY);
        configMap.put(URL_NAMESPACE_KEY, ENV_NAMESPACE_KEY);
    }
}
